package org.example.ims.Service.Order.Impl;

import org.example.ims.Entity.Order.TransferDetail;
import org.example.ims.Entity.Order.TransferOrder;
import org.example.ims.Entity.Base.Product;
import org.example.ims.Repository.Order.TransferDetailRepository;
import org.example.ims.Repository.Order.TransferOrderRepository;
import org.example.ims.Repository.Base.ProductRepository;
import org.example.ims.Repository.Base.WarehouseRepository;
import org.example.ims.Service.Order.TransferDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;

@Service("transferDetailService")
public class TransferDetailServiceImpl implements TransferDetailService {

    @Autowired
    private  TransferDetailRepository detailRepository;
    @Autowired
    private  TransferOrderRepository orderRepository;
    @Autowired
    private  ProductRepository productRepository;
    @Autowired
    private  WarehouseRepository warehouseRepository;

    @Override
    public TransferDetail createDetail(TransferDetail detail) {
        validateRelatedEntities(detail);
        return detailRepository.save(detail);
    }

    @Override
    public TransferDetail updateDetail(Integer detailId, TransferDetail detail) {
        TransferDetail existingDetail = detailRepository.findById(detailId)
                .orElseThrow(() -> new NoSuchElementException("TransferDetail not found with id: " + detailId));

        validateRelatedEntities(detail);

        if (detail.getQuantity() != null) {
            existingDetail.setQuantity(detail.getQuantity());
        }
        if (detail.getProductId() != null) {
            existingDetail.setProductId(detail.getProductId());
        }
        if (detail.getOrder() != null) {
            existingDetail.setOrder(detail.getOrder());
        }

        return detailRepository.save(existingDetail);
    }

    @Override
    public void deleteDetail(Integer detailId) {
        if (!detailRepository.existsById(detailId)) {
            throw new NoSuchElementException("TransferDetail does not exist with id: " + detailId);
        }
        detailRepository.deleteById(detailId);
    }

    @Override
    public TransferDetail getDetailById(Integer detailId) {
        return detailRepository.findById(detailId)
                .orElseThrow(() -> new NoSuchElementException("TransferDetail not found with id: " + detailId));
    }

    @Override
    public Page<TransferDetail> getAllDetails(Integer page, Integer size) {
        return detailRepository.findAll(PageRequest.of(page, size));
    }

    @Override
    public Page<TransferDetail> searchDetails(Integer orderId, Integer productId, Integer fromWarehouseId, Integer toWarehouseId, Integer page, Integer size) {
        return detailRepository.findAll(buildSpecification(orderId, productId), PageRequest.of(page, size));
    }

    @Override
    public Page<TransferDetail> getDetailsByOrderId(Integer orderId, Integer page, Integer size) {
        return detailRepository.findByOrderOrderId(orderId, PageRequest.of(page, size));
    }

    @Override
    public <T> List<T> convertOrderDetails(List<TransferDetail> details,Class<T> targetClass)throws Exception{
        // 这里只返回实体对象的设置，不是对数据库插入
        // 遍历details，创建对应的details即可
        List<T> list = new ArrayList<>();
        for(TransferDetail detail : details){
            T targetDetail = targetClass.getDeclaredConstructor().newInstance();
            // 使用反射设置productId
            targetClass.getMethod("setProductId", Integer.class)
                    .invoke(targetDetail, detail.getProductId());

            // 使用反射设置quantity
            targetClass.getMethod("setQuantity", Integer.class)
                    .invoke(targetDetail, detail.getQuantity());
            list.add(targetDetail);
        }
        return list;
    }


    private Specification<TransferDetail> buildSpecification(Integer orderId, Integer productId) {
        return (root, query, cb) -> {
            return cb.and(
                    orderId != null ? cb.equal(root.join("order").get("orderId"), orderId) : null,
                    productId != null ? cb.equal(root.join("product").get("productId"), productId) : null
            );
        };
    }

    private void validateRelatedEntities(TransferDetail detail) {
        if (detail.getOrder() != null && detail.getOrder().getOrderId() != null) {
            Optional<TransferOrder> order = orderRepository.findById(detail.getOrder().getOrderId());
            if (order.isEmpty()) {
                throw new NoSuchElementException("TransferOrder not found with id: " + detail.getOrder().getOrderId());
            }
        }

        if (detail.getProductId() != null) {
            Optional<Product> product = productRepository.findById(detail.getProductId());
            if (product.isEmpty()) {
                throw new NoSuchElementException("Product not found with id: " + detail.getProductId());
            }
        }

    }
}